import { Column, Table, TableHeaderProps } from "react-virtualized";
import React, { useState, useEffect, useRef } from 'react';
import { Resizable } from 'react-resizable';
import { useDrop, useDrag } from 'react-dnd';
import { HolderOutlined } from '@ant-design/icons';
import ViewForm from './ViewForm'
import './index.less'

const ITEM_HEIGHT = 40;

type ColumnKey = 'holderFixed' | 'serialFixed' | 'cmd' | 'target' | 'value' | 'opsFixed';

interface HandleProps {
    handleAxis: string;
    [key: string]: any;
}

// 行组件
const RowItem = ({ rowData, style, columnWidths, tableWidth, index, moveRow, addRow }: { rowData: any, style: any, columnWidths: any, tableWidth: any, index: number, moveRow: (dragIndex: number, hoverIndex: number) => void, addRow: (index: number, data: any) => void }) => {

    const ref = useRef<HTMLSpanElement>(null);
    const [{ isDragging }, drag, preview] = useDrag({
        type: 'ROW',
        item: { index, type: 'ROW' },
        collect: (monitor) => ({
            isDragging: monitor.isDragging(),
        }),
    });

    const [{ isOver, dropPosition }, drop] = useDrop({
        accept: ['ROW', 'COMMAND'],
        collect: (monitor) => {
            if (!ref.current) {
                return {
                    isOver: false,
                    dropPosition: null,
                };
            }

            const clientOffset = monitor.getClientOffset();
            if (!clientOffset) {
                return {
                    isOver: false,
                    dropPosition: null,
                };
            }

            const rect = ref.current.getBoundingClientRect();
            const hoverMiddleY = (rect.bottom - rect.top) / 2;
            const hoverClientY = clientOffset.y - rect.top;

            return {
                isOver: monitor.isOver(),
                dropPosition: hoverClientY < hoverMiddleY ? 'top' : 'bottom',
            };
        },
        drop: (item: { index: number, type: string, command: any }) => {
            if (item.type === 'COMMAND') {
                // 新增
                const hoverIndex = dropPosition === 'top' ? index : index + 1;
                addRow(hoverIndex, {
                    key: Date.now().toString(),
                    cmd: item.command.name,
                    target: 'Target',
                    value: 'Value',
                    ops: 'Ops'
                });
            } else if (item.type === 'ROW') {
                // 移动
                const dragIndex = item.index;
                const hoverIndex = dropPosition === 'bottom' ? index : index - 1;
                if (dragIndex === hoverIndex) {
                    return;
                }
                moveRow(dragIndex, hoverIndex);
                item.index = hoverIndex;
            }
        }
    });

    return (
        <div
            ref={(node) => {
                preview(node);
                drop(node);
            }}
            style={style}
            className={`row-item ${isDragging ? 'dragging' : ''} ${isOver ? `drop-${dropPosition}` : ''}`}

        >
            <div ref={(node) => {
                ref.current = node;
                drag(drop(ref));
            }} style={{
                width: columnWidths.holderFixed,
                cursor: 'move',
                marginRight: '5px'
            }}>
                <HolderOutlined />
            </div>
            <div className="row-col index-col" style={{ width: columnWidths.serialFixed }}>
                {index + 1}
            </div>
            <div className="row-col cmd-col" style={{ width: columnWidths.cmd * tableWidth }}>{rowData.cmd}</div>
            <div className="row-col target-col" style={{ width: columnWidths.target * tableWidth }}>{rowData.target}</div>
            <div className="row-col value-col" style={{ width: columnWidths.value * tableWidth }}>{rowData.value}</div>
            <div className="row-col ops-col" style={{ width: columnWidths.opsFixed }}>{rowData.ops}</div>
        </div>
    )
}

// 拖拽手柄
const ResizableHandle = React.forwardRef<HTMLDivElement, HandleProps>((props, ref) => {
    const { handleAxis, ...restProps } = props;
    return <div ref={ref} className={`column-resizable-handle handle-${handleAxis}`} {...restProps} >⋮</div>;
});

// 表格组件
const TableView = () => {
    const tableContainerRef = useRef<HTMLDivElement>(null);
    const [columnWidths, setColumnWidths] = useState<Record<ColumnKey, number>>({
        holderFixed: 30,
        serialFixed: 30,
        cmd: .3,
        target: .4,
        value: .3,
        opsFixed: 100
    });
    const [tableWidth, setTableWidth] = useState(0);
    const [tableHeight, setTableHeight] = useState(0);
    const [dataSource, setDataSource] = useState<any[]>([]);

    // 调整列宽
    const resizeColumnWidth = ({ dataKey, deltaX }: { dataKey: string; deltaX: number }) => {
        setColumnWidths((prevWidths) => {
            const percentDelta = deltaX / (tableWidth - prevWidths.holderFixed - prevWidths.serialFixed - prevWidths.opsFixed)
            let nextDataKey: ColumnKey

            switch (dataKey) {
                case 'cmd':
                    nextDataKey = 'target'
                    break
                case 'target':
                    nextDataKey = 'value'
                    break
                case 'value':
                    nextDataKey = 'opsFixed'
                    break
                default:
                    nextDataKey = 'target';
            }

            return {
                ...prevWidths,
                [dataKey as ColumnKey]: prevWidths[dataKey as ColumnKey] + percentDelta,
                [nextDataKey]: prevWidths[nextDataKey] - percentDelta
            }
        })
    };
    // 表头渲染
    const headerRenderer = (props: TableHeaderProps) => {
        const width = columnWidths[props.dataKey as ColumnKey] * tableWidth
        return (
            <Resizable
                key={props.dataKey}
                width={width}
                handle={<ResizableHandle />}
                onResize={(e, { size }) => {
                    resizeColumnWidth({
                        dataKey: props.dataKey as ColumnKey,
                        deltaX: size.width - width
                    })
                }}
                draggableOpts={{ enableUserSelectHack: false }}
                axis='x'
            >
                <div className="ReactVirtualized__Table__headerTruncatedText">
                    {props.label}
                </div>
            </Resizable>
        );
    };

    // 移动行
    const moveRow = (dragIndex: number, hoverIndex: number) => {
        const newData = [...dataSource];
        const [removed] = newData.splice(dragIndex, 1);
        newData.splice(hoverIndex, 0, removed);
        setDataSource(newData);
    };

    // 新增行
    const addRow = (index: number, data: any) => {
        const newData = [...dataSource];
        newData.splice(index, 0, {
            ...data,
            key: Date.now().toString(),
        });
        setDataSource(newData);
    };

    // 监听窗口大小变化
    useEffect(() => {
        const onWindowResize = () => {
            if (tableContainerRef.current) {
                setTableWidth(tableContainerRef.current.clientWidth);
                setTableHeight(tableContainerRef.current.clientHeight);
            }
        }
        onWindowResize()
        window.addEventListener('resize', onWindowResize)
        return () => {
            window.removeEventListener('resize', onWindowResize)
        }
    }, [columnWidths]);

    // 模拟数据
    useEffect(() => {
        setDataSource(Array.from({ length: 20 }, (_, index) => ({
            key: Math.floor(Math.random() * 50) + 20,
            id: index,
            cmd: `Cmd-${index}`,
            target: `Target-${index}`,
            value: `Value-${index}`,
            ops: `Ops-${index}`
        })))
    }, []);

    return (
        <div className="table-view" >
            <div className="command-table-wrapper" ref={tableContainerRef}>
                <Table
                    className='command-table'
                    width={tableWidth}
                    height={tableHeight}
                    headerHeight={ITEM_HEIGHT}
                    rowHeight={ITEM_HEIGHT}
                    rowCount={dataSource.length}
                    rowGetter={({ index }) => dataSource[index]}
                    rowRenderer={({ rowData, key, index, style }) => {
                        return (
                            <RowItem
                                index={index}
                                rowData={rowData}
                                key={key}
                                style={style}
                                columnWidths={columnWidths}
                                tableWidth={tableWidth}
                                moveRow={moveRow}
                                addRow={addRow}
                            />
                        );
                    }}
                >
                    <Column
                        label=""
                        dataKey="holder"
                        width={columnWidths.holderFixed}
                    />
                    <Column
                        label=""
                        dataKey="serial"
                        width={columnWidths.serialFixed}
                    />
                    <Column
                        headerRenderer={headerRenderer}
                        label="命令"
                        dataKey="cmd"
                        width={columnWidths.cmd * tableWidth}
                    />
                    <Column
                        headerRenderer={headerRenderer}
                        label="目标"
                        dataKey="target"
                        width={columnWidths.target * tableWidth}
                    />
                    <Column
                        label="值"
                        dataKey="value"
                        width={columnWidths.value * tableWidth}
                    />
                    <Column
                        dataKey="ops"
                        label="操作"
                        width={columnWidths.opsFixed}
                    />
                </Table>
            </div>
            <ViewForm />
        </div>
    );
};

export default TableView;
